周回スコア計算
周回スコア表の計算プログラム
クランバトル第41回(2021/07)以降に対応しています。
第79回(2024/09)の調整まで実装。
プログラミング言語Pythonの仕様により、コピペした後にインデントを調整する必要があります。
#!/usr/bin/env python3
from fractions import Fraction
from sys import argv
# クランバトルの仕様。開催年*100+開催月
version = 299912
try:
s = argv[1]
if s != '-':
version = int(s)
except LookupError:
pass
# 出力する周回数の最大値
loop_max = 50
try:
s = argv[2]
if s != '-':
loop_max = int(s)
except LookupError:
pass
#
# ここからデータ設定
#
# 古すぎる仕様ではロジックが流用できない
assert version >= 202107
# ボスのHPの単位, HP一覧表の各値にこの値が掛かる
hp_unit = 1000000
# 各ボスのHPの一覧
boss_hp = []
# 3段階目まで
if False:
pass
elif version >= 202402:
boss_hp.append( [ 9,12,15,18,23] )
boss_hp.append( [12,15,20,23,30] )
boss_hp.append( [35,40,45,50,58] )
elif version >= 202304:
boss_hp.append( [ 6, 8,10,12,15] )
boss_hp.append( [ 8,10,13,15,20] )
boss_hp.append( [20,22,25,28,30] )
else:
boss_hp.append( [ 6, 8,10,12,15] )
boss_hp.append( [ 6, 8,10,12,15] )
boss_hp.append( [12,14,17,19,22] )
# 4段階目(全5段階の場合のみ)
if False:
pass
elif version >= 202304:
pass
elif version >= 202204:
boss_hp.append( [22,23,27,29,31] )
else:
boss_hp.append( [19,20,23,25,27] )
# 最終段階
if False:
pass
elif version >= 202409:
boss_hp.append( [700,720,760,780,800] )
elif version >= 202406:
boss_hp.append( [600,620,660,680,700] )
elif version >= 202402:
boss_hp.append( [540,560,600,620,640] )
elif version >= 202309:
boss_hp.append( [270,280,300,310,320] )
elif version >= 202304:
boss_hp.append( [200,210,230,240,250] )
elif version >= 202209:
boss_hp.append( [145,150,175,195,210] )
elif version >= 202206:
boss_hp.append( [105,110,125,140,150] )
elif version >= 202109:
boss_hp.append( [ 95,100,110,120,130] )
else:
boss_hp.append( [ 85, 90, 95,100,110] )
# 各ボスのスコア倍率の一覧
# ボスHP*スコア倍率 が整数になるようにすること
boss_mult = []
boss_mult.append( [ Fraction(x,10) for x in [12,12,13,14,15] ] )
boss_mult.append( [ Fraction(x,10) for x in [16,16,18,19,20] ] )
if False:
pass
elif version >= 202304:
boss_mult.append( [ Fraction(x,10) for x in [20,20,21,21,22] ] )
boss_mult.append( [ Fraction(x,10) for x in [45,45,47,48,50] ] )
else:
boss_mult.append( [ Fraction(x,10) for x in [20,20,24,24,26] ] )
boss_mult.append( [ Fraction(x,10) for x in [35,35,37,38,40] ] )
boss_mult.append( [ Fraction(x,10) for x in [35,35,37,38,40] ] )
# 次の段階に切り替わる周回数の境界
# 途中の段階から開始する場合は、開始する段階まで0に設定する
loop_sep = []
if False:
pass
elif version >= 202309:
loop_sep = [ 0, 6,22]
elif version >= 202304:
loop_sep = [ 3, 9,25]
elif version >= 202112:
loop_sep = [ 3,10,30,38]
else:
loop_sep = [ 3,10,30,40]
#
# データの要素数の整合性チェック
#
assert len(boss_hp) == len(boss_mult)
for hp, mult in zip(boss_hp,boss_mult):
assert len(hp) > 0
assert len(hp) == len(mult)
assert len(loop_sep) == len(boss_hp)-1
for i in range(len(loop_sep)-1):
assert loop_sep[i] >= 0
assert loop_sep[i] <= loop_sep[i+1]
#
# ここから計算ロジック
#
stage_scores = [] # 各段階の、全ボスを1体ずつ倒した場合の合計スコア
stage_scores_diff = [] # 各段階の途中周回での、完了に必要な最大値と最小値の差
for i in range(len(boss_hp)):
scores = []
for hp, mult in zip(boss_hp[i], boss_mult[i]):
scores.append( round(hp_unit * hp * mult) )
score = sum(scores)
score_diff = score - min(scores)
stage_scores.append(score)
stage_scores_diff.append(score_diff)
loop_scores = [] # 各周回の、周回完了に必要なスコアの最小値と最大値の対
stage_loop_begin = [0] + loop_sep[:]
stage_loop_end = loop_sep[:] + [loop_max+1]
score = 0
for i in range(len(loop_sep)+1):
loop_begin = stage_loop_begin[i]
loop_end = stage_loop_end[i]
if loop_begin >= loop_end:
continue
for j in range(loop_end - loop_begin - 1):
score += stage_scores[i]
score_min = score
score_max = score + stage_scores_diff[i]
loop_scores.append( (score_min, score_max) )
if i < len(loop_sep):
score += stage_scores[i]
loop_scores.append( (score, score) )
#
# ここから計算結果の出力
#
for iloop,v in enumerate(loop_scores,1):
score_min, score_max = v
if score_min == score_max:
print( '|{:d}|>|CENTER:{:,d}|'.format(iloop, score_min) )
else:
print( '|{:d}|{:,d}|{:,d}|'.format(iloop, score_min, score_max) )